﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NativeWrapperIFilter;
using System.Runtime.InteropServices;

namespace DocumentsTagger.TextMiningUtils
{
    public static class TextMiningUtil
    {
        private static readonly char[] SPLIT_TOKENS = new Char[] { ' ','~','!','@','#','$','%','^','&','*','(',')','_','+','`','}','{','[',']','\\','|','\'','\"',';',':','?','/','.','>',',','<', '\r','\n','\t' };
        
        

        /// <summary>
        /// Gets a histogram of a file. 
        /// <remarks>does not load all the file content into memory hance much better compared to using GetWordsFromText and GetDocContent</remarks>
        /// </summary>
        /// <param name="fileFullPath">the file to get its histogram</param>
        /// <returns>a dictionary with the counting of every valid word in the file</returns>
        public static Dictionary<string, int> GetWordsFromFile(string fileFullPath)
        {
            Dictionary<string, int> res = new Dictionary<string, int>();

            char[] buffer = new char[4096];
            StringBuilder sb = new StringBuilder();
            int currPosition = 0;
            string[] words;
            try
            {
                using (FilterReader fr = new FilterReader(fileFullPath))
                {
                    int amountRead;
                    while (0 != (amountRead = fr.ReadBlock(buffer, 0, 4096)))
                    {
                        currPosition = 0;
                        sb.Append(buffer, 0, amountRead);
                        words = sb.ToString().Split(SPLIT_TOKENS);
                        for (int i = 0; i < words.Length-1; i++)
                        {
                            currPosition += words[i].Length + 1;
                            if (res.ContainsKey(words[i]))
                            {
                                res[words[i]]++;
                            }
                            else
                            {
                                res.Add(words[i], 1);
                            }
                        }

                        sb.Remove(0, currPosition);
                    }



                    if (sb.Length > 0)
                    {
                        words = sb.ToString().Split(SPLIT_TOKENS);
                        for (int i = 0; i < words.Length; i++)
                        {
                            if (res.ContainsKey(words[i]))
                            {
                                res[words[i]]++;
                            }
                            else
                            {
                                res.Add(words[i], 1);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // if we got an error - we return empty dictionary
                res.Clear();
            }

            return res;
        }

        /// <summary>
        /// gets the words array from given text
        /// </summary>
        /// <param name="text">the text to split into words</param>
        /// <remarks>Obselete, use GetWordsFromFile (unless you know what you are doing)</remarks>
        /// <returns>array of words</returns>
        public static string[] GetWordsFromText(string text)
        {
            string[] words = null;

            words = text.Split(SPLIT_TOKENS, StringSplitOptions.RemoveEmptyEntries);

            return words;
        }

        /// <summary>
        /// gets the content of a file using the right IFilter 
        /// </summary>
        /// <param name="FileFullPath">The full path to the file</param>
        /// <remarks>Obselete, use GetWordsFromFile (unless you know what you are doing)</remarks>
        /// <returns>string builder object with the file's content</returns>
        public static StringBuilder GetDocContent(string FileFullPath)
        {
            char[] buffer = new char[4096];
            StringBuilder sb = new StringBuilder();
            try
            {
                using (FilterReader fr = new FilterReader(FileFullPath))
                {
                    int amountRead;
                    while (0 != (amountRead = fr.ReadBlock(buffer, 0, 4096)))
                    {
                        sb.Append(buffer, 0, amountRead);
                    }

                }
            }
            catch (Exception ex)
            {
                // if we got an error - we return empty string.
                sb.Clear();
            }
            return sb;
        }

        /// <summary>
        /// checkes for validity of string to learning mechanizm
        /// </summary>
        
        /// <param name="word">the text to check</param>
        /// <returns>true if valid to learn from, false otherwise</returns>
        internal static bool IsValidWord(string word)
        {
            bool isValid = false;
            
            if (word.Trim().Length >= 2)
            {
                isValid = true;
            }

            return isValid;
        }

        /// <summary>
        /// removes white spaces from beginning and ending of word.
        /// </summary>
        /// <param name="word">the text to senityze</param>
        /// <returns>cleaned string</returns>
        internal static string SenityzeWord(string word)
        {
            string senityzedWord = word;

            senityzedWord = senityzedWord.Trim();

            return senityzedWord;
        }
    }
}
